package com.newtouch.cq.base.starter.business.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.newtouch.cq.base.starter.business.entity.SysMenu;
import com.newtouch.cq.base.starter.business.entity.SysOrganization;
import com.newtouch.cq.base.starter.business.model.UserDetailsImpl;
import com.newtouch.cq.base.starter.business.model.vo.MenuVO;
import com.newtouch.cq.base.starter.business.model.vo.UserVO;
import com.newtouch.cq.base.starter.business.service.IBaseSysMenuService;
import com.newtouch.cq.base.starter.business.service.IBaseSysOrganizationService;
import com.newtouch.cq.base.starter.business.service.IBaseSysUserService;
import com.newtouch.cq.base.starter.business.service.ISecurityUserDetailsService;
import com.newtouch.cq.base.starter.lang.em.MenuTypeEnum;
import com.newtouch.cq.lang.cache.CacheAble;
import com.newtouch.cq.lang.config.CacheProperties;
import com.newtouch.cq.lang.config.TokenCacheProperties;
import com.newtouch.cq.lang.em.BaseExceptionEnum;
import com.newtouch.cq.lang.em.StatusEnum;
import com.newtouch.cq.lang.exception.MccBizException;
import com.newtouch.cq.lang.util.LogUtil;
import com.newtouch.cq.lang.util.ServletUtils;
import com.newtouch.cq.security.exception.AuthException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SecurityUserDetailsServiceImpl implements ISecurityUserDetailsService {


    @Resource
    private IBaseSysUserService userService;

    @Resource
    private IBaseSysMenuService menuService;

    @Resource
    private IBaseSysOrganizationService organizationService;

    @Resource
    private CacheAble cacheAble;

    private Log log = LogFactory.get(SecurityUserDetailsServiceImpl.class);

    @Override
    public UserDetails loadUserByUsername(String username) {
//        verifyCode();
        UserVO userVO = userService.findUserVOByUsername(username);
        return loadUserByUserVO(userVO);
    }

    private void verifyCode() {
        HttpServletRequest request = ServletUtils.getRequest();
        String code = request.getParameter("code");
        String randomKey = request.getParameter("randomKey");
        if(TokenCacheProperties.enableloginValidateCode && StrUtil.isNotEmpty(randomKey)) {
            if(StrUtil.isEmpty(code)) {
                throw new DisabledException("验证码不能为空");
            }
            String cacheCode = (String) cacheAble.get(CacheProperties.imageCodePrifix+randomKey);
            if(StrUtil.equals(code, cacheCode)) {
                cacheAble.delete(CacheProperties.imageCodePrifix+randomKey);
            } else  {
                cacheAble.delete(CacheProperties.imageCodePrifix+randomKey);
                throw new DisabledException("验证码错误或已过期");
//                throw new MccBizException(BaseExceptionEnum.ARGUMENT_VALIDATE_EXCEPTION).setMessage("验证码错误,或者已过期");
            }
        }
    }

    private UserDetails loadUserByUserVO(UserVO userVO) {
        if (userVO == null) {
            LogUtil.error(log,BaseExceptionEnum.ACCOUNT_PASSWORD_ERROR);
            throw new AuthException(BaseExceptionEnum.ACCOUNT_PASSWORD_ERROR);
        }
        if (StatusEnum.VALID != userVO.getStatus()) {
            LogUtil.error(log,BaseExceptionEnum.ACCOUNT_DISABLE);
            throw new AuthException(BaseExceptionEnum.ACCOUNT_DISABLE);
        }

        List<MenuVO> menuVOS = menuService.selectUserMenu(userVO.getId());

        UserDetailsImpl user = new UserDetailsImpl(userVO, menuVOS);
        String userKey = TokenCacheProperties.prifix + user.getId();
        String tokenKey = RandomUtil.randomStringUpper(TokenCacheProperties.length);
        user.setUserKey(userKey);
        user.setTokenKey(tokenKey);
        user.setAccountNonLocked(true);
        List<? extends SysMenu> menuList = menuService.selectUserMenu(userVO.getId());
        List<String> userPermissions = CollUtil.newArrayList();
        menuList.stream().forEach(menu -> {
            if(MenuTypeEnum.FUN == menu.getType()) {
                userPermissions.add(menu.getUrl());
            }
        });
        user.setUserPermissions(userPermissions);
        List<SysOrganization> orgList = organizationService.selectAuthList(userVO.getId(),userVO.getOrgId());
        List<Long> orgIdList = orgList.stream().map(SysOrganization::getId).collect(Collectors.toList());
        user.setOrgIdList(orgIdList);
        return user;
    }

}
